package com.solo.system.web;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.solo.common.core.global.R;
import com.solo.common.logger.annotation.Logger;
import com.solo.common.logger.enums.LoggerType;
import com.solo.common.orm.core.query.Wrappers;
import com.solo.satoken.utils.LoginHelper;
import com.solo.system.api.consts.notice.NoticeScope;
import com.solo.system.api.consts.notice.NoticeStatus;
import com.solo.system.api.entity.SysNotice;
import com.solo.system.model.message.MessageResp;
import com.solo.system.model.notice.SysNoticeConvert;
import com.solo.system.model.notice.req.NoticeCreateReq;
import com.solo.system.model.notice.req.NoticeQueryReq;
import com.solo.system.model.notice.req.NoticeUpdateReq;
import com.solo.system.model.notice.resp.NoticeGetResp;
import com.solo.system.model.notice.resp.NoticeListResp;
import com.solo.system.service.SysNoticeService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;

import static com.mybatisflex.core.query.QueryMethods.*;
import static com.solo.system.api.entity.table.SysNoticeTableDef.SysNoticeTable;
import static com.solo.system.api.entity.table.SysNoticeUserTableDef.SysNoticeUserTable;

/**
 * 通知公告控制器
 * @author 十一
 * @since 2024-12-02 17:27
 * 人生若只如初见，何事秋风悲画扇
 **/
@RestController
@RequiredArgsConstructor
@RequestMapping("/system/notice")
public class SysNoticeController {

    private final SysNoticeService sysNoticeService;

    /**
     * 新增通知公告
     * @param req 通知公告新增对象
     * @return 响应信息
     */
    @PostMapping
    @SaCheckPermission("system-notice-create")
    @Logger(value = "新增通知公告", type = LoggerType.CREATE)
    public R<Boolean> create(@Valid @RequestBody NoticeCreateReq req) {
        return R.success(sysNoticeService.create(req));
    }

    /**
     * 删除通知公告
     * @param noticeIds 通知公告集合
     * @return 响应信息
     */
    @DeleteMapping("/{noticeIds}")
    @SaCheckPermission("system-notice-delete")
    @Logger(value = "删除通知公告", type = LoggerType.DELETE)
    public R<Boolean> delete(@PathVariable Long[] noticeIds) {
        return R.success(sysNoticeService.removeByIds(Arrays.asList(noticeIds)));
    }

    /**
     * 更新通知公告
     * @param req 通知公告更新对象
     * @return 响应信息
     */
    @PutMapping
    @SaCheckPermission("system-notice-update")
    @Logger(value = "更新通知公告", type = LoggerType.UPDATE)
    public R<Boolean> update(@Valid @RequestBody NoticeUpdateReq req) {
        return R.success(sysNoticeService.update(req));
    }

    @PutMapping("/publish/{noticeId}")
    @SaCheckPermission("system-notice-publish")
    @Logger(value = "发布通知公告", type = LoggerType.UPDATE)
    public R<Boolean> publish(@PathVariable Long noticeId) {
        return R.success(sysNoticeService.publish(noticeId));
    }

    @PutMapping("/quash/{noticeId}")
    @SaCheckPermission("system-notice-quash")
    @Logger(value = "撤销通知公告", type = LoggerType.UPDATE)
    public R<Boolean> quash(@PathVariable Long noticeId) {
        return R.success(sysNoticeService.quash(noticeId));
    }

    /**
     * 获取通知公告
     * @param noticeId 通知公告
     * @return 响应信息
     */
    @GetMapping("/{noticeId}")
    @SaCheckPermission("system-notice-query")
    public R<NoticeGetResp> get(@PathVariable Long noticeId) {
        return R.success(SysNoticeConvert.INSTANCE.convertGet(sysNoticeService.getById(noticeId)));
    }

    /**
     * 分页查询通知公告列表
     * @param page 分页对象
     * @param req 通知公告查询对象
     * @return 响应信息
     */
    @GetMapping("/page")
    @SaCheckPermission("system-notice-query")
    public R<Page<NoticeListResp>> page(Page<NoticeListResp> page, NoticeQueryReq req) {
        Page<NoticeListResp> list = sysNoticeService.pageAs(page, Wrappers.builder(req), NoticeListResp.class);
        return R.success(list);
    }

    /**
     * 分页查询我的通知公告
     * @param page 页面
     * @param req 绿色
     * @return {@link R }<{@link Page }<{@link NoticeListResp }>>
     */
    @GetMapping("/my-page")
    public R<Page<MessageResp>> myPage(Page<SysNotice> page, NoticeQueryReq req) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .select(SysNoticeTable.DefaultColumns)
                .leftJoin(
                        select(SysNoticeUserTable.DefaultColumns).from(SysNoticeUserTable)
                                .where(SysNoticeUserTable.UserId.eq(LoginHelper.getUserId()))
                ).as("nu").on(SysNoticeTable.NoticeId.eq(raw("nu.notice_id")))
                .where(SysNoticeTable.Status.eq(NoticeStatus.PUBLISH))
                .and(
                        bracket(SysNoticeTable.Scope.eq(NoticeScope.ALL_USERS).and("nu.notice_id IS NULL"))
                        .or(SysNoticeTable.Scope.eq(NoticeScope.SPECIFY_THE_USER).and("nu.is_read = b'0'"))
                )
                .orderBy(SysNoticeTable.Level.desc(), SysNoticeTable.SendTime.desc());
        Page<SysNotice> noticePage = sysNoticeService.page(page, queryWrapper);
        return R.success(SysNoticeConvert.INSTANCE.convertMessage(noticePage));
    }
}
